import sys
from sanic import Sanic, response

from app.api_v1.Permissions import Permission


from . import config
from sanic.exceptions import NotFound, SanicException
from .api_v1 import api_bp
from sanic_cors import CORS
from sanic.response import HTTPResponse, json, text, html, redirect

from jinja2 import Environment, FileSystemLoader, select_autoescape

from .WTFs import LoginForm, RegisterForm, HostForm, OrderForm

from sanic_session import Session

from app.api_v1.models import db, User, Host, Order

from app.Decorators import permission_required

# 注册app
app = Sanic('idc')
# CORS(app, automatic_options=True)

app.static('/static', 'app/static')
app.static('/host/update/static', 'app/static')
Session(app)


# 注册api蓝图
# app.blueprint(api_bp)

# 导入配置文件
app.config.update_config(config)

template_paths=['app/templates']
#sync
env_sync = Environment(loader=FileSystemLoader(template_paths),
                        auto_reload=select_autoescape(['html','xml']),
                        enable_async=False)
#async
enable_async_flag = sys.version_info >= (3,6)
env_sync = Environment(loader=FileSystemLoader(template_paths),
                        auto_reload=select_autoescape(['html','xml']),
                        enable_async=enable_async_flag)

#sync render template
def template_render_sync(template_file, **kwargs):
    template = env_sync.get_template(template_file)
    rendered_template = template.render(kwargs)
    return html(rendered_template)

#async render template
async def template_render_async(template_file, **kwargs):
    template = env_sync.get_template(template_file)
    rendered_template = await template.render_async(kwargs)
    return html(rendered_template)

# 404
@app.exception(NotFound)
async def ignore_404s(request, exception):
    title="404s"
    content="Ooops!~页面未找到!&sim;"

    # data = {"title": title, "content": content}
    data = {"title": title, "content": content, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    # data = { "tips": tips, "form": form, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='404.html', **data)

@app.route("/sanicexception")
async def no_no(request):
        raise SanicException("Something went wrong.", status_code=501)

@app.route('/', methods=['GET', 'POST'])
async def handle_request(request):
    tips = '首页'
    title="首页"
    content="首页页面&sim;"

    data = {"title": title, "content": content, "tips": tips, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='index.html', **data)

@app.route('/register', methods=['GET', 'POST'])
async def register(request):
    tips = '注册'
    form = RegisterForm(request)
    # current_request = Request.get_current()
    # print(f'current_request : {current_request}')
    print(f'name : {form.name.data}')
    print(f'password : {form.password.data}')
    print(f'confirm : {form.confirm.data}')
    # request.args.get('token') ?token=xxxx
    # print(f'验证码 : {request.token}')
    if request.method == 'POST' and form.validate():
        token = request.form.get('token')
        if None == token:
            tips = '😭验证码未通过验证'
        else:
            with db.atomic():
                user_id = User.insert(name=form.name.data, pwd=form.password.data, role='user').execute()
                user = User.get_or_none(id=user_id)
                if None == user:
                    tips = '😭注册失败'
                else:
                    tips = '🥰注册成功<a href="/login">登陆</a>'
    else:
        # tips = '🥺注册信息有问题'
        pass
    
    data = { "tips": tips, "form": form, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='register.html', **data)

@app.route('/login', methods=['GET', 'POST'])
async def login(request):
    tips = '登陆'
    form = LoginForm(request)
    print(f'login from { form} ')
    if request.method == 'POST' and form.validate():
        name = request.form.get('name')
        password = request.form.get('password')
        token = request.form.get('token')
        print(f'name : {name}')
        print(f'password : {password}')
        print(f'token : {token}')
        
        print(f'ttttttttttttttttttttttttttt')
        
        name = form.name.data
        password = form.password.data
        token = request.form.get('token')
        print(f'name : {name}')
        print(f'password : {password}')
        print(f'token : {token}')
        user = User.get_or_none(name=name)
        if None == user.pwd or user.pwd != password:
            form.password.errors.insert(0, '🙃密码错误')
            # raise ValidationError('🙃密码错误')
        else:
            if None == token:
                tips = '😭验证码未通过验证'
            else:
                request.ctx.session['isLogin'] = True
                request.ctx.session['username'] = name
                request.ctx.session['userbalance'] = user.balance
                # return redirect('/')
                data = { "tips": tips, "form": form, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
                return await template_render_async(template_file='index.html', **data)
    else:
        pass
    
    data = { "tips": tips, "form": form, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='login.html', **data)

@app.get("/logout")
async def logout(request):
    request.ctx.session['username'] = None
    request.ctx.session['userbalance'] = None
    request.ctx.session['isLogin'] = False
    return redirect('/')

@app.route('/host', methods=['GET', 'POST'])
@permission_required(Permission.Admin)
async def host(request):
    form = HostForm(request)
    # for sub in form.server_type:
        # print( sub(**{'class': 'outline pv3 ma2 tc'}) )

    tips = '添加主机节点'
    hosts= {}

    ip = form.ip.data
    print(f' ip : {ip}')
    area = form.area.data
    print(f' area : {area}')
    login_url = form.login_url.data
    print(f' login_url : {login_url}')
    server_type = form.server_type.data
    print(f' server_type : {server_type}')

    hosts = Host.select().execute()

    if request.method == 'POST' and form.validate():
        print(f'cross post and validate()....')
    else:
        print(f'nnnnnnnnnnnooooooooooooooooooooo cross post and validate()....')

    data = {"hosts": hosts, "form": form, "tips": tips, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='host.html', **data)

@app.get("/host/del/<hid:int>")
async def del_host_by_id(request, hid:int):
    tips = ''
    hosts = Host.select().execute()

    host = Host.get_or_none(id=hid)
    if host != None:
        Host.delete_instance(host, recursive=True)
        tips = 'ipv4网络地址删除成功'
        return redirect('/host')

    data = {"hosts": hosts, "tips": tips, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='host.html', **data)

@app.route("/host/update/<hid:int>", methods=['GET', 'POST'])
async def update_host_by_id(request, hid:int):
    tips = ''
    form = HostForm(request)
    hosts = Host.select().execute()

    host = Host.get_or_none(id=hid)

    from wtforms import Label
    form.submit.label = Label(form.submit.id, '更新')
    
    if request.method == 'POST':
        print(f'update cross post and validate()....')
        print(f'update form.server_password.data : { form.server_password.data }')
        # hid = (Host
        #         .insert(host.asdict())
        #         .on_conflict(
        #             conflict_target=[Host.id],
        #             preserve=[],
        #             update={Host.server_type: ( ( 1 << 1 ) | ( 1 << 2 ) )})
        #             .execute()
        #         )

        # print(f'hid : {hid} .')
        uhost = (Host.update(ip = form.ip.data,
                             login_url = form.login_url.data,
                             server_type = ( ( 1 << 4 ) | ( 1 << 3 ) ),
                             server_url = form.server_url.data,
                             server_provider = form.server_provider.data,
                             security_code = form.security_code.data,
                             server_account = form.server_account.data,
                             server_password = form.server_password.data,
                             ).where(Host.area == form.area.data).execute()
                )
        print(f'uhost : {uhost}')     
    else:
        print(f'update nnnnnnnnnnnooooooooooooooooooooo cross post and validate()....')
        form.ip.data = host.ip
        form.area.data = host.area
        form.login_url.data = host.login_url
        # form.server_state.data = host.server_state
        # form.server_type.data = host.server_type
        print(f'form : {form} ....')
        print(f'host.server_type : {host.server_type} ....')
        form.server_provider.data = host.server_provider
        form.server_url.data = host.server_url
        
        # form.server_type.data = (1,3)
        
        form.security_code.data = host.security_code
        form.server_account.data = host.server_account
        form.server_password.data = host.server_password
        print(f' form.server_password.data : { form.server_password.data }')
    
    data = {"host": host, "form": form, "tips": tips, "isLogin": request.ctx.session.get('isLogin'), "username": request.ctx.session.get('username'), "userbalance": request.ctx.session.get('userbalance')}
    return await template_render_async(template_file='updatehost.html', **data)

# from app.api_v1.models import EmployeeInfo, db

# db.create_tables([EmployeeInfo], safe=True)